Frontend Forever App
We have a mobile app for you to download and use. And you can unlock many features in the app.
Get it now
Intall Later
Run
HTML
CSS
Javascript
Output
Document
@charset "UTF-8"; @import url(https://fonts.googleapis.com/css?family=Nunito+Sans:300,400,600,700,800); *, :after, :before { box-sizing: border-box; padding: 0; margin: 0; } @import 'normalize.css'; :root { --width: 140px; --aspect-ratio: 2.12 / 2.62; } * { box-sizing: border-box; } html { color-scheme: light only; } @media (prefers-color-scheme: dark) { html { color-scheme: dark only; } } [data-theme='light'] { color-scheme: light only; } [data-theme='dark'] { color-scheme: dark only; } body { display: grid; place-items: center; min-height: 100vh; overflow-x: hidden; background: color-mix(in lch, canvas, canvasText 10%); } body::before { --size: 45px; --line: color-mix(in lch, canvasText, transparent 85%); content: ''; height: 100vh; width: 100vw; position: fixed; background: linear-gradient( 90deg, var(--line) 1px, transparent 1px var(--size) ) 50% 50% / var(--size) var(--size), linear-gradient(var(--line) 1px, transparent 1px var(--size)) 50% 50% / var(--size) var(--size); mask: linear-gradient(-25deg, transparent 30%, white); top: 0; transform-style: flat; pointer-events: none; z-index: -1; } ul { list-style-type: none; margin: 0; padding: 0; } li { width: var(--width); aspect-ratio: var(--aspect-ratio); } ul { display: flex; } .bear-link { color: canvasText; position: fixed; top: 1rem; left: 1rem; width: 48px; aspect-ratio: 1; display: grid; place-items: center; opacity: 0.8; } :where(.x-link, .bear-link):is(:hover, :focus-visible) { opacity: 1; } .bear-link svg { width: 75%; } /* Polaroid styling */ .polaroid__wrapper { position: relative; width: var(--width); aspect-ratio: var(--aspect-ratio); transform: rotate(var(--rotation, 6deg)) scale(var(--scale, 1)); } .polaroid { --spread: 6px; --dot: hsl(74 29% 92%); width: calc(100% - 1rem); height: calc(100% - 1rem); background: radial-gradient(var(--dot) 1px, transparent 1px), radial-gradient(var(--dot) 1px, transparent 1px), hsl(74 29% 100%); background-size: var(--spread) var(--spread); background-position: 0 0, calc(var(--spread) * 0.5) calc(var(--spread) * 0.5); padding: calc((0.2 / 3.5) * var(--width)); overflow: hidden; display: flex; flex-direction: column; margin: 0; } .polaroid__img { background: hsl(0 0% 10%); width: 100%; aspect-ratio: 1; } .polaroid__shadow { background: hsl(0 0% 10% / 0.5); position: absolute; inset: 1rem; z-index: -1; opacity: var(--opacity, 0.2); filter: blur(5px); transform: translate(var(--translation, 10%), var(--translation, 10%)) scale(var(--scale, 1)); } ul { transition: width 0.25s; } li { scale: 1; transition-property: width, translate, display; transition-duration: 0.25s, 0.25s, 1s; transition-behavior: allow-discrete; &[hidden] { width: 0; } @starting-style { width: 0; } } /* li[hidden] { width: 0; } */ /* @starting-style { li { width: 0; } } */ .polaroid__wrapper { translate: 0 0; transition: translate, transform, opacity; transition-duration: 1s, 0.25s, 1s; transition-behavior: allow-discrete; transition-timing-function: linear( 0 0%, 0.5007 7.21%, 0.7803 12.29%, 0.8883 14.93%, 0.9724 17.63%, 1.0343 20.44%, 1.0754 23.44%, 1.0898 25.22%, 1.0984 27.11%, 1.1014 29.15%, 1.0989 31.4%, 1.0854 35.23%, 1.0196 48.86%, 1.0043 54.06%, 0.9956 59.6%, 0.9925 68.11%, 1 100% ), ease, ease; } li[hidden] .polaroid__wrapper { translate: 0 calc(50vh + 100%); opacity: 0; transition-timing-function: ease; } @starting-style { .polaroid__wrapper { translate: 0 50vh; opacity: 0; } } .polaroid__img { filter: brightness(1) saturate(0.95) sepia(30%); transition: filter 0.5s 0.5s; } @starting-style { .polaroid__img { filter: brightness(0) saturate(0.95) sepia(30%); } } [data-stagger='true'] li { --rotation: calc( 6deg + (sin((var(--index) / var(--items)) * 210deg) * -12deg) ); translate: 0 calc(sin((var(--index) / var(--items)) * 210deg) * 50%); }
console.log("Event Fired") import { Pane } from 'https://cdn.skypack.dev/tweakpane' const list = document.querySelector('ul') const syncList = () => { list.style.setProperty( '--items', list.querySelectorAll('li:not([hidden])').length ) for (let c = 0; c < list.children.length; c++) { list.children[c].style.setProperty('--index', c) } } const pushItem = () => { const li = Object.assign(document.createElement('li'), { innerHTML: `
`, }) list.appendChild(li) li.addEventListener('click', async () => { li.hidden = true list.style.setProperty( '--items', list.querySelectorAll('li:not([hidden])').length ) await Promise.allSettled(li.getAnimations().map((a) => a.finished)) li.remove() syncList() }) syncList() } const popItem = async () => { const items = list.querySelectorAll('li:not([hidden])') const item = items[items.length - 1] item.hidden = true list.style.setProperty( '--items', list.querySelectorAll('li:not([hidden])').length ) await Promise.allSettled(item.getAnimations().map((a) => a.finished)) item.remove() syncList() } const config = { theme: 'system', stagger: false, } const ctrl = new Pane({ title: 'Config', expanded: true, }) const push = ctrl.addButton({ title: 'Push' }) push.on('click', pushItem) const pop = ctrl.addButton({ title: 'Pop' }) pop.on('click', popItem) ctrl.addBinding(config, 'stagger', { label: 'Stagger', }) ctrl.addBinding(config, 'theme', { options: { System: 'system', Light: 'light', Dark: 'dark', }, label: 'Theme', }) const sync = () => { document.documentElement.dataset.theme = config.theme document.documentElement.dataset.stagger = config.stagger } sync() const handle = (event) => { if ( !document.startViewTransition || event.target.controller.view.labelElement.innerText !== 'Theme' ) return sync() document.startViewTransition(() => sync()) } const build = () => { pushItem() if (list.children.length < 3) requestAnimationFrame(build) } build() ctrl.on('change', handle)